<!DOCTYPE html>
<html>

<head>
	<meta charset="utf-8">
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<title>zxing-cpp/wasm reader demo</title>
	<link rel="shortcut icon" href="#" />
	<script src="zxing_reader.js"></script>
	<script>
var zxing = ZXing().then(function(instance) {
	zxing = instance; // this line is supposedly not required but with current emsdk it is :-/
});

async function readBarcodes() {
	let format = document.getElementById("format").value;
	let file = document.getElementById("file").files[0];

	let arrayBuffer = await file.arrayBuffer();
	let u8Buffer = new Uint8Array(arrayBuffer);

	let zxingBuffer = zxing._malloc(u8Buffer.length);
	zxing.HEAPU8.set(u8Buffer, zxingBuffer);
	let results = zxing.readBarcodesFromImage(zxingBuffer, u8Buffer.length, true, format, 0xff);
	zxing._free(zxingBuffer);

	showResults(results);
	showImageWithResults(file, results);
}

function showImageWithResults(file, results) {
	var canvas = document.getElementById("canvas");
	var img = new Image()
	img.addEventListener('load', function() {
		canvas.width = img.width;
		canvas.height = img.height;
		const ctx = canvas.getContext("2d");
		ctx.drawImage(img, 0, 0);

		for (let i = 0; i < results.size(); i += 1) {
			const { position } = results.get(i);
			// Draw outline square
			ctx.beginPath();
			ctx.moveTo(position.topLeft.x, position.topLeft.y);
			ctx.lineTo(position.topRight.x, position.topRight.y);
			ctx.lineTo(position.bottomRight.x, position.bottomRight.y);
			ctx.lineTo(position.bottomLeft.x, position.bottomLeft.y);
			ctx.closePath();
			ctx.strokeStyle = "red";
			ctx.lineWidth = 4;
			ctx.stroke();

			// Draw number inside square
			const text = {
				text: i + 1,
				size: Math.abs((position.bottomRight.y - position.topLeft.y)) / 2,
				x: (position.topLeft.x + position.bottomRight.x) / 2.0,
				y: (position.topLeft.y + position.bottomRight.y) / 2.0,
			};
			ctx.fillStyle = "white";
			ctx.font = `bold ${text.size}px sans`;
			ctx.textAlign = "center";
			ctx.textBaseline = "middle";
			ctx.fillText(text.text, text.x, text.y);
			ctx.strokeStyle = "red";
			ctx.lineWidth = 2;
			ctx.strokeText(text.text, text.x, text.y);
		}
	});
	img.src = URL.createObjectURL(file)
}

function escapeTags(htmlStr) {
	return htmlStr.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
}

function u8a2hex(bytes) {
	return bytes.reduce((a, b) => a + b.toString(16).padStart(2, '0') + ' ', '');
}

function showResults(results) {
	const resultsDiv = document.getElementById("results");
	resultsDiv.innerHTML = "";
	if (results.size() === 0) {
		resultsDiv.innerHTML += "No " + (document.getElementById("format").value || "barcode") + " found";
	}
	else {
		for (let i = 0; i < results.size(); i += 1) {
			const { format, text, bytes, error } = results.get(i);
			resultsDiv.innerHTML += "<li>Format: <strong>" + format + "</strong>"
				+ "<pre>" + (escapeTags(text) || '<font color="red">Error: ' + error + '</font>') + "</pre>"
				+ "<pre>" + u8a2hex(bytes) + "</pre>"
				+ "</li>";
		}
	}
}
	</script>
</head>

<body style="text-align: left">
	<h2>zxing-cpp/wasm reader demo</h2>
	<p>
		This is a simple demo of the wasm wrapper of <a href="https://github.com/zxing-cpp/zxing-cpp">zxing-cpp</a>
		scanning for barcodes in image files.
	</p>
	<p></p>
	<div>
		Scan Format:
		<select id="format" onchange='readBarcodes()'>
			<option value="" selected="">Any</option>
			<option value="Aztec">Aztec</option>
			<option value="Codabar">Codabar</option>
			<option value="Code39">Code 39</option>
			<option value="Code93">Code 93</option>
			<option value="Code128">Code 128</option>
			<option value="DataMatrix">DataMatrix</option>
			<option value="DataBar">DataBar</option>
			<option value="DataBarExpanded">DataBarExpanded</option>
			<option value="DXFilmEdge">DXFilmEdge</option>
			<option value="EAN8">EAN-8</option>
			<option value="EAN13">EAN-13</option>
			<option value="ITF">ITF</option>
			<option value="PDF417">PDF417</option>
			<option value="QRCode">QR Code</option>
			<option value="MicroQRCode">Micro QRCode</option>
			<option value="RMQRCode">rMQR Code</option>
			<option value="UPCA">UPC-A</option>
			<option value="UPCE">UPC-E</option>
			<option value="LinearCodes">Linear Codes</option>
			<option value="MatrixCodes">Matrix Codes</option>
		</select>

		&nbsp;&nbsp;

		Image File: <input id="file" type="file" accept="image/png, image/jpeg" onchange="readBarcodes()" />

		<br /><br />

		<canvas id="canvas" width="640" height="480"></canvas>

		<br /><br />

		<ol id="results"></ol>

	</div>
</body>

</html>
